/**
 * 
 */
package com.star.util.xml;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

/**
 * @ClassName: JAXBUtil
 * @Description: TODO
 * @author starhq
 * @createtime 2014年7月31日 下午4:43:26
 * @email : jian.wang@shinsoft.net
 * @modify by TODO
 * @resaon
 * @edittime
 * @version 1.0
 * @copyright shinsoft
 */
public class JAXBUtil {

	private static ConcurrentHashMap<Class<?>, JAXBContext> jaxbContextMap = new ConcurrentHashMap<Class<?>, JAXBContext>();

	/**
	 * 
	 * @Description: 对象转xml
	 * @author starhq
	 * @createtime 2014年8月1日 上午10:19:36
	 * @email : jian.wang@shinsoft.net
	 * @edit @{todo}
	 * @edittime
	 * @version 1.0
	 * @throws IOException
	 * @copyright shinsoft
	 */
	public static <T> String objectToXml(Class<T> clazz, T t, boolean format)
			throws JAXBException, IOException {
		JAXBContext jc = null;
		if (jaxbContextMap.get(clazz) == null) {
			Map<String, String> properties = new HashMap<String, String>();
			jc = JAXBContext.newInstance(new Class<?>[] { clazz }, properties);
			jaxbContextMap.put(clazz, jc);
			// jc = jaxbContextMap.putIfAbsent(clazz, JAXBContext.newInstance(
			// new Class<?>[] { clazz }, properties));
		} else {
			jc = jaxbContextMap.get(clazz);
		}
		Marshaller u = jc.createMarshaller();
		if (format)
			u.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

		StringWriter sw = new StringWriter();
		u.marshal(t, sw);
		sw.close();
		return sw.toString();
	}

	/**
	 * 
	 * @Description: xml转对象
	 * @author starhq
	 * @createtime 2014年8月1日 上午10:33:04
	 * @email : jian.wang@shinsoft.net
	 * @edit @{todo}
	 * @edittime
	 * @version 1.0
	 * @copyright shinsoft
	 */
	@SuppressWarnings("unchecked")
	public static <T> T xmlToObject(Class<T> clazz, String xml)
			throws JAXBException {
		JAXBContext jc = null;
		if (jaxbContextMap.get(clazz) == null) {
			Map<String, String> properties = new HashMap<String, String>();
			jc = JAXBContext.newInstance(new Class<?>[] { clazz }, properties);
			jaxbContextMap.put(clazz, jc);
			// jc = jaxbContextMap.putIfAbsent(clazz, JAXBContext.newInstance(
			// new Class<?>[] { clazz }, properties));
		} else {
			jc = jaxbContextMap.get(clazz);
		}
		Unmarshaller us = jc.createUnmarshaller();
		StringReader sr = new StringReader(xml);
		T t = (T) us.unmarshal(sr);
		sr.close();
		return t;
	}

	public static <T> void objectToFile(Class<T> clazz, T t, File file,
			boolean format) throws JAXBException {
		JAXBContext jc = null;
		if (jaxbContextMap.get(clazz) == null) {
			Map<String, String> properties = new HashMap<String, String>();
			jc = jaxbContextMap.putIfAbsent(clazz, JAXBContext.newInstance(
					new Class<?>[] { clazz }, properties));
		} else {
			jc = jaxbContextMap.get(clazz);
		}
		Marshaller ms = jc.createMarshaller();
		if (format) {
			ms.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
		}
		ms.marshal(t, file);
	}

	public static <T> void objectToFile(Class<T> clazz, T t, File file)
			throws JAXBException {
		objectToFile(clazz, t, file, true);
	}

	@SuppressWarnings("unchecked")
	public static <T> T fileToObject(Class<T> clazz, File file)
			throws JAXBException {
		JAXBContext jc = null;
		if (jaxbContextMap.get(clazz) == null) {
			Map<String, String> properties = new HashMap<String, String>();
			jc = jaxbContextMap.putIfAbsent(clazz, JAXBContext.newInstance(
					new Class<?>[] { clazz }, properties));
		} else {
			jc = jaxbContextMap.get(clazz);
		}
		Unmarshaller us = jc.createUnmarshaller();
		return (T) us.unmarshal(file);
	}

	@SuppressWarnings("unchecked")
	public static <T> T streamToObject(Class<T> clazz, InputStream in)
			throws JAXBException {
		JAXBContext jc = null;
		if (jaxbContextMap.get(clazz) == null) {
			Map<String, String> properties = new HashMap<String, String>();
			jc = jaxbContextMap.putIfAbsent(clazz, JAXBContext.newInstance(
					new Class<?>[] { clazz }, properties));
		} else {
			jc = jaxbContextMap.get(clazz);
		}
		Unmarshaller us = jc.createUnmarshaller();
		return (T) us.unmarshal(in);
	}

	public static <T> String objectToXml(Class<T> clazz, T t)
			throws JAXBException, IOException {
		return objectToXml(clazz, t, true);
	}

	public static void main(String[] args) throws JAXBException, IOException {
		// long start = System.currentTimeMillis();
		// Persons persons = new Persons();
		// persons.setPersons(new ArrayList<Person>(2));
		//
		// Person p = new Person();
		// p.setBirthDay(new Date());
		// p.setUserId(1);
		// p.setUsername("王坚");
		//
		// Person p1 = new Person();
		// p1.setBirthDay(new Date());
		// p1.setUserId(2);
		// p1.setUsername("小胖");
		//
		// persons.getPersons().add(p);
		// persons.getPersons().add(p1);

		// System.out.println(getObjectToXml(Persons.class, persons));

		// String xml =
		// "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
		// + "<person>" + "<userId>1</userId>"
		// + " <username>王坚</username>"
		// + "<birthDay>2014-08-01T10:33:35.784+08:00</birthDay>"
		// + "</person>";
		// Person person = xmlToObject(Person.class, xml);
		// System.out.println(objectToXml(Person.class, p, true));
		// String xml =
		// "<?xml version='1.0' encoding='UTF-8' standalone='yes'?><persons><person><userId>1</userId><username>王坚</username><birthDay>2014-08-01T13:11:40.462+08:00</birthDay></person><person><userId>2</userId><username>小胖</username><birthDay>2014-08-01T13:11:40.463+08:00</birthDay></person></persons>";
		// fileToObject(Persons.class, new File("D:\\persons.xml"));
		// System.out.println("--------------------------");
		// System.out.println(System.currentTimeMillis() - start);

		String xml = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
				+ "<user>" + " <passWord>12345678</passWord>"
				+ " <UserName>starhq</UserName>" + "</user>";

		System.out.println(xmlToObject(User.class, xml).getUserName());
	}
}
